package com.lsq.baseadmin.common.utils;

import com.google.gson.Gson;
import org.springframework.util.ClassUtils;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLDecoder;
import java.util.*;

/**
 * @author pc12138
 * @date 2020/10/30 17:43
 */
public class EnumUtil {

    /**
     * 更新公共的枚举生成js文件
     *
     */
    public static void updateEnum() throws IOException{
        InputStream is = EnumUtil.class.getResourceAsStream("/templates/templateEnum.js");
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String s;
        StringBuffer sb = new StringBuffer();
        while((s = br.readLine()) != null) {
            sb = sb.append(s);
        }
        String resultStr = sb.toString().replace("#{enums}", buildJsonString());

        InputStream newIs = new ByteArrayInputStream(resultStr.getBytes());
        AliyunOssUtil.uploadEnumJs(newIs);

    }

    private static String buildJsonString() {
        List<Class<?>> classList = getClasses("com.lsq.baseadmin.common.enums");

        Map<String, Map> map = new HashMap<>();
        for (Class clazz : classList) {
            String className = clazz.getName();
            int index = className.lastIndexOf(".");
            String typeName = className.substring(index + 1);
            int suffixIndex = typeName.indexOf("Enum");
            typeName = typeName.substring(0, suffixIndex);

            Map<String, Map> instanceMap = new HashMap<>();
            Object[] objects = clazz.getEnumConstants();
            for (Object obj : objects) {
                Map<String, Object> fieldMap = new HashMap<>();
                try {
                    Method getValue = clazz.getMethod("getValue");
                    Method getName = clazz.getMethod("getLabel");
                    fieldMap.put("value", getValue.invoke(obj));
                    fieldMap.put("label", getName.invoke(obj));
                } catch (NoSuchMethodException e) {
                    continue;
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
                instanceMap.put(obj.toString(), fieldMap);
            }
            if (!instanceMap.isEmpty()) {
                map.put(typeName, instanceMap);
            }
        }

        return new Gson().toJson(map);
    }

    private static List<Class<?>> getClasses(String packageName) {
        List<Class<?>> classes = new ArrayList<>();
        //是否循环迭代
        boolean recursive = true;

        //获取包的名字 并进行替换
        String packageDirName = packageName.replace('.', '/');

        //定义一个枚举的集合 并进行循环来处理这个目录下的things
        Enumeration<URL> dirs;

        try {
            dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);

            //循环迭代下去
            while (dirs.hasMoreElements()) {
                //获取下一个元素
                URL url = dirs.nextElement();
                //得到协议的名称
                String protocol = url.getProtocol();
                //如果是以文件的形式保存在服务器上
                if ("file".equals(protocol)) {
                    //获取包的物理路径
                    String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
                    //以文件的方式扫描整个包下的文件 并添加到集合中
                    findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return classes;
    }

    private static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive, List<Class<?>> classes) {
        //获取此包的目录 建立一个File
        File dir = new File(packagePath);
        //如果不存在或者 也不是目录就直接返回
        if (!dir.exists() || !dir.isDirectory()) {
            return;
        }

        //如果存在 就获取包下的所有文件 包括目录
        //自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
        File[] dirFiles = dir.listFiles(file -> (recursive && file.isDirectory()) || (file.getName().endsWith(".class")));

        if(null == dirFiles) {
            return;
        }

        //循环所有文件
        for (File file : dirFiles) {
            //如果是目录 则继续扫描
            if (file.isDirectory()) {
                findAndAddClassesInPackageByFile(packageName + "." + file.getName(),
                        file.getAbsolutePath(),
                        recursive,
                        classes);
            } else {
                //如果是java类文件 去掉后面的.class 只留下类名
                String className = file.getName().substring(0, file.getName().length() - 6);
                try {
                    //添加到集合中去
                    classes.add(Class.forName(packageName + '.' + className));
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    public static void main(String[] args) throws IOException {
        InputStream is = EnumUtil.class.getResourceAsStream("/templates/templateEnum.js");
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String s;
        StringBuffer sb = new StringBuffer();
        while((s = br.readLine()) != null) {
            sb = sb.append(s);
        }
        String resultStr = sb.toString().replace("#{enums}", buildJsonString());
        String fileDirPath = "/src/main/resources/static/js/enums.js";
        String c = System.getProperty("user.dir");
        FileOutputStream fos = new FileOutputStream(c + fileDirPath);
        fos.write(resultStr.getBytes());
        is.close();
        fos.close();
    }
}
